from scipy.optimize import curve_fit
import numpy as np
import pickle
import yaml
import re

class EMax():
    def __init__(self):
        self.params = None
    
    def func(self,x,e0,em,e50):
        return e0+em*(x)/(e50+x)

    def fit(self,x,y):
        popt, pcov = curve_fit(self.func, x, y,method='dogbox')
        self.params = popt
    
    def predict(self,x):
        return self.func(x,*self.params)
    @property
    def e50(self):
        return self.params[2]

    @property
    def e0(self):
        return self.params[0]

    @property
    def em(self):
        return self.params[0]
    
    def save(self,path):
        with open(path,'wb')as f:
            pickle.dump(self.params,f)

    def load(self,path):
        with open(path,'rb') as f:
            self.params = pickle.load(f)

def load_yaml_config(file):
    loader = yaml.SafeLoader
    loader.add_implicit_resolver(
    u'tag:yaml.org,2002:float',
    re.compile(u'''^(?:
    [-+]?(?:[0-9][0-9_]*)\\.[0-9_]*(?:[eE][-+]?[0-9]+)?
    |[-+]?(?:[0-9][0-9_]*)(?:[eE][-+]?[0-9]+)
    |\\.[0-9_]+(?:[eE][-+][0-9]+)?
    |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*
    |[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$''', re.X),
    list(u'-+0123456789.'))
    with open(file,'r') as f:
        configs = yaml.safe_load(f)
    return configs

def searchKey(keyword,config:dict):
    '''BFS
    '''
    tlist = []
    for k,v in config.items():
        if k == keyword:
            return config[keyword]
        tlist.append(v)
    for v in tlist:
        if type(v) is not dict:
            continue
        tmp = searchKey(keyword,v)
        if tmp is not None:
            return tmp
    
def findPeak(x):
    left = 0
    right = len(x)-1
    while(left<right):
        mid = (left+right+1)>>1
        if (x[mid-1]<x[mid] and x[mid]<x[mid+1]):
            left = mid
        elif (x[mid-1]>x[mid] and x[mid]>x[mid+1]):
            right = mid
        else:
            return mid